package com.hontech.bread.utils

import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.view.View
import com.hontech.bread.store.writeError
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import kotlinx.serialization.json.Json
import org.greenrobot.eventbus.EventBus

object AppTask : Handler(Looper.getMainLooper())

private class Task2(name: String) : HandlerThread(name) {
    init {
        start()
    }
}

object ConnTask : Handler(Task2("conn").looper)
object CPUTask : Handler(Task2("cpu").looper)
object NetTask : Handler(Task2("net").looper)

suspend fun <T> CompletableDeferred<T>.await(timeout: Long, msg: String): T {
    try {
        return withTimeout(timeout) {
            await()
        }
    } catch (e: TimeoutCancellationException) {
        throw TimeoutException(msg)
    }
}

suspend fun <T> runAny(handler: Handler, cb: () -> T): T {
    val task = Task(cb)
    handler.post(task)
    return task.await()
}

suspend fun <T> runIO(cb: () -> T): T {
    val task = Task(cb)
    ConnTask.post(task)
    return task.await()
}

suspend fun <T> runNet(cb: () -> T): T {
    val task = Task(cb)
    NetTask.post(task)
    return task.await()
}

suspend fun <T> runCPU(cb: () -> T): T {
    val task = Task(cb)
    CPUTask.post(task)
    return task.await()
}

suspend fun <T> runNewThread(cb: () -> T): T {
    val promise = CompletableDeferred<T>()
    Thread {
        try {
            val v = cb()
            promise.complete(v)
        } catch (e: Exception) {
            promise.completeExceptionally(e)
        }
    }.start()
    return promise.await()
}

class Task<T>(private val cb: () -> T) : Runnable {

    private val promise = CompletableDeferred<T>()

    suspend fun await(): T {
        return promise.await()
    }

    override fun run() {

        try {
            val r = cb()
            promise.complete(r)
        } catch (e: Exception) {
            promise.completeExceptionally(e)
        }
    }
}


private val uiScope = MainScope()
private var lastClickTimestamp = System.currentTimeMillis()

fun View.onClick(cb: suspend () -> Unit) {
    setOnClickListener {
        val current = System.currentTimeMillis()
        if (current - lastClickTimestamp > 500) {
            lastClickTimestamp = current
            uiScope.launch { cb() }
        }
    }
}


fun runOnUi(cb: suspend CoroutineScope.() -> Unit) {
    uiScope.launch {
        cb(this)
    }
}

fun runOnUiCatchAny(cb: suspend CoroutineScope.() -> Unit) {
    uiScope.launch {
        try {
            cb()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}


private val bus = EventBus.builder().logNoSubscriberMessages(false).build()
val globalJson = Json {
    encodeDefaults = true
    ignoreUnknownKeys = true
}


fun registerEvent(o: Any) {
    if (bus.isRegistered(o)) {
        return
    }
    bus.register(o)
}

fun unregister(o: Any) {
    if (bus.isRegistered(o)) {
        bus.unregister(o)
    }
}

fun postEvent(event: Any) {
    bus.post(event)
}


suspend inline fun execIgnore(cb: () -> Unit) {
    try {
        cb()
    } catch (e: Exception) {
        e.printStackTrace()
        writeError(e)
    }
}







